﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls;

namespace ShredTheLog.Controls
{
    public sealed class MultiBorder : Decorator
    {
        public Thickness Padding
        {
            get { return (Thickness)GetValue(PaddingProperty); }
            set { SetValue(PaddingProperty, value); }
        }
        public static readonly DependencyProperty PaddingProperty = DependencyProperty.Register("Padding", typeof(Thickness), typeof(MultiBorder), new FrameworkPropertyMetadata(new Thickness(), FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));

        public Brush Background
        {
            get { return (Brush)GetValue(BackgroundProperty); }
            set { SetValue(BackgroundProperty, value); }
        }
        public static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register("Background", typeof(Brush), typeof(MultiBorder));
        
        public Thickness BorderThickness
        {
            get { return (Thickness)GetValue(BorderThicknessProperty); }
            set { SetValue(BorderThicknessProperty, value); }
        }
        public static readonly DependencyProperty BorderThicknessProperty = DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(MultiBorder), new FrameworkPropertyMetadata(new Thickness(), FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));

        public Brush LeftBorderBrush
        {
            get { return (Brush)GetValue(LeftBorderBrushProperty); }
            set { SetValue(LeftBorderBrushProperty, value); }
        }
        public static readonly DependencyProperty LeftBorderBrushProperty = DependencyProperty.Register("LeftBorderBrush", typeof(Brush), typeof(MultiBorder), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender | FrameworkPropertyMetadataOptions.AffectsRender));

        public Brush TopBorderBrush
        {
            get { return (Brush)GetValue(TopBorderBrushProperty); }
            set { SetValue(TopBorderBrushProperty, value); }
        }
        public static readonly DependencyProperty TopBorderBrushProperty = DependencyProperty.Register("TopBorderBrush", typeof(Brush), typeof(MultiBorder), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender | FrameworkPropertyMetadataOptions.AffectsRender));

        public Brush RightBorderBrush
        {
            get { return (Brush)GetValue(RightBorderBrushProperty); }
            set { SetValue(RightBorderBrushProperty, value); }
        }
        public static readonly DependencyProperty RightBorderBrushProperty = DependencyProperty.Register("RightBorderBrush", typeof(Brush), typeof(MultiBorder), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender | FrameworkPropertyMetadataOptions.AffectsRender));

        public Brush BottomBorderBrush
        {
            get { return (Brush)GetValue(BottomBorderBrushProperty); }
            set { SetValue(BottomBorderBrushProperty, value); }
        }
        public static readonly DependencyProperty BottomBorderBrushProperty = DependencyProperty.Register("BottomBorderBrush", typeof(Brush), typeof(MultiBorder), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender | FrameworkPropertyMetadataOptions.AffectsRender));

        protected override void OnRender(DrawingContext drawingContext)
        {
            drawingContext.DrawRectangle(Background, null, new Rect(0, 0, ActualWidth, ActualHeight));
            drawingContext.DrawRectangle(LeftBorderBrush, null, new Rect(0, 0, BorderThickness.Left, ActualHeight));
            drawingContext.DrawRectangle(RightBorderBrush, null, new Rect(ActualWidth - BorderThickness.Right, 0, BorderThickness.Right, ActualHeight));
            var topPath = new PathFigure(new Point(0, 0), new PathSegment[] { new PolyLineSegment(new Point[] { new Point(ActualWidth, 0), new Point(ActualWidth - BorderThickness.Right, BorderThickness.Top), new Point(BorderThickness.Left, BorderThickness.Top) }, false) }, true);
            drawingContext.DrawGeometry(TopBorderBrush, null, new PathGeometry(new PathFigure[] { topPath }));
            var bottomPath = new PathFigure(new Point(0, ActualHeight), new PathSegment[] { new PolyLineSegment(new Point[] { new Point(ActualWidth, ActualHeight), new Point(ActualWidth - BorderThickness.Right, ActualHeight - BorderThickness.Bottom), new Point(BorderThickness.Left, ActualHeight - BorderThickness.Bottom) }, false) }, true);
            drawingContext.DrawGeometry(BottomBorderBrush, null, new PathGeometry(new PathFigure[] { bottomPath }));
        }

        private static Rect HelperDeflateRect(Rect rt, Thickness thick)
        {
            return new Rect(rt.Left + thick.Left, rt.Top + thick.Top, Math.Max((double)0.0, (double)((rt.Width - thick.Left) - thick.Right)), Math.Max((double)0.0, (double)((rt.Height - thick.Top) - thick.Bottom)));
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            Thickness borderThickness = this.BorderThickness;
            Rect rt = new Rect(finalSize);
            Rect rect2 = HelperDeflateRect(rt, borderThickness);
            UIElement child = this.Child;
            if (child != null)
            {
                Rect finalRect = HelperDeflateRect(rect2, this.Padding);
                child.Arrange(finalRect);
            }
            return finalSize;
        }

        private static Size HelperCollapseThickness(Thickness th)
        {
            return new Size(th.Left + th.Right, th.Top + th.Bottom);
        }

        protected override Size MeasureOverride(Size constraint)
        {
            UIElement child = this.Child;
            Size size = new Size();
            Size size2 = HelperCollapseThickness(this.BorderThickness);
            Size size3 = HelperCollapseThickness(this.Padding);
            if (child != null)
            {
                Size size4 = new Size(size2.Width + size3.Width, size2.Height + size3.Height);
                Size childConstraint = new Size(Math.Max((double)0.0, (double)(constraint.Width - size4.Width)), Math.Max((double)0.0, (double)(constraint.Height - size4.Height)));
                //Helper.SetMeasureDataOnChild(this, child, childConstraint);
                child.Measure(childConstraint);
                Size desiredSize = child.DesiredSize;
                size.Width = desiredSize.Width + size4.Width;
                size.Height = desiredSize.Height + size4.Height;
                return size;
            }
            return new Size(size2.Width + size3.Width, size2.Height + size3.Height);
        }
    }
}
